﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Service
{
    public static class ServiceCollectionExpand
    {
        /// <summary>
        /// 按特性中的生命周期注入业务组件
        /// </summary>
        /// <param name="service"></param>
        public static void AddServiceInject(this IServiceCollection service)
        {
            // 获取有ServiceAttribute特性的所有类
            //此方法只能获取当前程序域已经加载的程序集
            List<Type> types = AppDomain.CurrentDomain
                .GetAssemblies()
                .SelectMany(x => x.GetTypes())
                .Where(t => t.IsClass && !t.IsAbstract
                        && t.GetCustomAttributes(typeof(ServiceAttribute), false).Length > 0
                        )
                .ToList();
            //List<Type> types = GetTypesWithServiceAttribute();
            types.ForEach(impl =>
            {
                // 获取该类所继承的所有接口
                Type[] interfaces = impl.GetInterfaces();
                // 获取该类注入的生命周期
                var lifetime = impl.GetCustomAttribute<ServiceAttribute>().LifeTime;

                interfaces.ToList().ForEach(i =>
                {
                    switch (lifetime)
                    {
                        case ServiceLifetime.Singleton:
                            service.AddSingleton(i, impl);
                            break;
                        case ServiceLifetime.Scoped:
                            service.AddScoped(i, impl);
                            break;
                        case ServiceLifetime.Transient:
                            service.AddTransient(i, impl);
                            break;
                    }
                });
            });
        }

        /// <summary>
        /// DependencyContext.Default.CompileLibraries方法获取编译时引用的程序集
        /// </summary>
        /// <returns>带有ServiceAttribute特性的类型列表</returns>
        public static List<Type> GetTypesWithServiceAttribute()
        {
            var compileLibraries = DependencyContext.Default.CompileLibraries;
            var typesWithServiceAttribute = new List<Type>();

            foreach (var library in compileLibraries)
            {
                try
                {
                    var assembly = Assembly.Load(new AssemblyName(library.Name));
                    var types = assembly.GetTypes()
                        .Where(t => t.IsClass && !t.IsAbstract
                                    && t.GetCustomAttributes(typeof(ServiceAttribute), false).Length > 0)
                        .ToList();
                    typesWithServiceAttribute.AddRange(types);
                }
                catch (Exception ex)
                {
                    // 处理加载程序集时可能发生的异常
                    Console.WriteLine($"Error loading assembly {library.Name}: {ex.Message}");
                }
            }

            return typesWithServiceAttribute;
        }

    }
}